/*
 * =====================================================================================
 *       Filename:  dispatcher.c
 *         Author:  MIEN
 *    Description:  分发队列消息到订阅者
 *           Date:  2016-11-15 16:37
 * =====================================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lib/circle.h"
#include "http/http.h"
#include "client.h"
#include "config.h"
#include "dispatcher.h"

/* 通知分发的消息队列 */
static circleQueue* _circle = NULL;

/* 用于分发数据的缓冲区 */
static char _body[HTTP_BUFFER_SIZE];
static char _data[HTTP_BUFFER_SIZE];

/* 转换节点的value数据
 * data 和 (*value) 都是 queue* 类型，直接赋值，无需转换 */
static void _produce(void *data, void **value)
{
    (*value) = data;
}

/* 分发 */
static void _dispatch (void* value) {
    queue* q = (queue*) value;
    while (q->size > 0) {
        char *auth = getConfig("queue_auth");
        http_entity_t *http = client_request("GET", getConfig("server_host"), getConfig("server_port"), q->name, auth, NULL);
        if (strlen(http->body) == 0) {
            break;
        }
        strcpy(_body, http->body);

        subscriber* s = q->suber;
        while (s != NULL) {
            /* 
             * 分析订阅地址的最后一部分的fragment段
             * 例如: http://www.abc.com/user/hah?c=1#fragment
             * 
             * 如果有:
             * fragment作为分发的字段名，类似表单的字段名进行处理，信息进行url_encode编码。
             * 这样在订阅地址直接处理即可
             * php代码类似: $msg = $_POST['fragment'];
             *
             * 如果无:
             * 信息是post的整个content部分
             * php代码应如: $raw_post_data = file_get_contents('php://input');
             * 
             */
            char *fragment = strrchr(s->url, '#');
            if (fragment != NULL && strlen(++fragment) > 0) {
                sprintf(_data, "%s=", fragment);
                int len = strlen(_data);
                url_encode(_body, _data + len, HTTP_BUFFER_SIZE - len);
                client_request_ex("POST", s->url, NULL, _data);
            } else {
                client_request_ex("POST", s->url, NULL, _body);
            }
            s = s->next;
        }
    }
}

/* 初始 */
void initDispatcher()
{
    _circle = circleCreate();

    circleSetProduceMethod(_circle, _produce);
    circleSetConsumeMethod(_circle, _dispatch);

    circleAddConsumer(_circle);
    circleLoop(_circle);
}

/* 释放 */
void freeDispatcher()
{
    circleQuit(_circle);
    circleRelease(_circle);
}

/* 通知 */
void notify(queue* queue) {
    circlePushIn(_circle, queue);
}

